#include "stdafx.h"
#include "socket.h"
#include "ShareData/ShareData.h"
#include "Network.h"

using namespace std;

const INT CNetwork::UM_SEND_STRING = WM_USER + 1;

const INT kServerPort = 921;

CNetwork::CNetwork()
    : m_pData(NULL)
    , m_hThreadServ(NULL)
    , m_nThreadServId(0)
    , m_hThreadClient(NULL)
    , m_nThreadClientId(0)
    , m_dwStamp(0)
    , m_bExit(false)
    , m_pServer(NULL)
    , m_pClient(NULL)
    , m_bSend(0)
{

}

CNetwork::~CNetwork()
{
    _uninit();
}

bool CNetwork::Init(CShareData* pData)
{
    if (!pData)
        return false;

    m_pData = pData;

    m_pData->RegisterListener(this);

    unsigned uRetServ = 0;
    m_hThreadServ = (HANDLE)_beginthreadex(NULL, 0, ServThreadFunc, this, 0, &uRetServ);
    m_nThreadServId = ::GetThreadId(m_hThreadServ);

    return true;
}

bool CNetwork::InitClient(const std::string& strIpAddress)
{
    m_strIpAddress = strIpAddress;

    unsigned uRetClient = 0;
    m_hThreadClient = (HANDLE)_beginthreadex(NULL, 0, ClientThreadFunc, this, 0, &uRetClient);
    m_nThreadClientId = ::GetThreadId(m_hThreadClient);

    return true;
}

void CNetwork::SendLine(std::string str)
{
    m_strSend = str;
}

std::string CNetwork::GetLine()
{
    return m_strRecv;
}

bool CNetwork::OnDataChanged(DWORD dwStamp)
{
    if (m_dwStamp != dwStamp)
    {
        if (!::InterlockedExchange(&m_bSend, 1))
            ::PostThreadMessage(m_nThreadClientId, UM_SEND_STRING, 0, 0);
    }
    return true;
}

unsigned CNetwork::RunServThread()
{
    SocketServer in(kServerPort,1);
    m_pServer = in.Accept();

    while (1)
    {
        std::string str = m_pServer->ReceiveLine();
        m_dwStamp = m_pData->WriteString(str);
    }

    return 0;
}

unsigned CNetwork::RunClientThread()
{
    if (m_pClient)
    {
        delete m_pClient;
        m_pClient = NULL;
    }

    m_pClient = new (std::nothrow) SocketClient(m_strIpAddress, kServerPort);
   if (!m_pClient)
        return 1;

    CopyData data_;
    MSG msg = {0};
    ::InterlockedExchange(&m_bSend, 0);
    while (GetMessage(&msg, NULL, 0, 0))
    {
        if (msg.message == UM_SEND_STRING)
        {
            m_pData->GetData(data_);
            if (E_CDT_STRING == data_.type)
                m_pClient->SendLine(data_.str);
            ::InterlockedExchange(&m_bSend, 0);
        }
    }

    return 0;
}

unsigned CNetwork::ServThreadFunc(void* p)
{
    CNetwork* pNet = (CNetwork*)(p);
    if (pNet)
        return pNet->RunServThread();
    return 0;
}

unsigned CNetwork::ClientThreadFunc(void* p)
{
    CNetwork* pNet = (CNetwork*)(p);
    if (pNet)
        return pNet->RunClientThread();
    return 0;
}

bool CNetwork::_uninit()
{
    m_pData->UnregisterListener(this);

    m_bExit = true;

    HANDLE objects[] = {m_hThreadServ, m_hThreadClient};
    ::WaitForMultipleObjects(2, objects, TRUE, 1000);

    if (m_hThreadServ)
    {
        ::CloseHandle(m_hThreadServ);
        m_hThreadServ = NULL;
        m_nThreadServId = 0;
    }

    if (m_hThreadClient)
    {
        ::CloseHandle(m_hThreadClient);
        m_hThreadClient = NULL;
        m_nThreadClientId = 0;
    }

    return true;
}